/*
 * Project: Sudoku Hint Engine for Android
 * Copyright (C) 2010-2013 Emanuel Moecklin
 * 
 * Available under the terms of the Lesser General Public License (LGPL)
 */
package com.onegravity.sudoku.solver.rules.uniqueness;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.net.Uri;

import com.onegravity.sudoku.solver.HintResource;
import com.onegravity.sudoku.solver.HintType;
import com.onegravity.sudoku.solver.core.IndirectHint;
import com.onegravity.sudoku.solver.core.Rule;
import com.onegravity.sudoku.solver.data.Cell;
import com.onegravity.sudoku.solver.data.ImmutableCell;
import com.onegravity.sudoku.solver.util.BitSetFactory;
import com.onegravity.sudoku.solver.util.HtmlLoader;
import com.onegravity.sudoku.solver.util.Link;

public class AvoidableRectangleHint extends IndirectHint implements Rule {

	private static final long serialVersionUID = -2836551837474894338L;
	
	private final List<Cell> rectangleCells;
	private final int a;
	private final int b;
	private final int x;

	private final boolean isType2;
	
    public AvoidableRectangleHint(List<Cell> rectangleCells, int a, int b, Map<Cell, BitSet> removablePotentials) {
        super(removablePotentials);
        this.rectangleCells = rectangleCells;
        this.a = a;
        this.b = b;
        this.x = 0;
        this.isType2 = false;
    }

    public AvoidableRectangleHint(List<Cell> rectangleCells, int a, int b, int x, Map<Cell, BitSet> removablePotentials) {
        super(removablePotentials);
        this.rectangleCells = rectangleCells;
        this.a = a;
        this.b = b;
        this.x = x;
        this.isType2 = true;
    }

    @Override
    public Collection<Cell> getSelectedCells(HintType hintType) {
    	switch(hintType) {
    	case SMALL_CLUE: return rectangleCells;
    	default:
    	case BIG_CLUE:
    	case HINT:
    		List<Cell> tmp = new ArrayList<Cell>(rectangleCells);
    		tmp.remove(3);
    		if (isType2) tmp.remove(2);
    		return tmp;
    	}
    }

    @Override
    public Map<Cell, BitSet> getSelectedPotentials(HintType hintType, int viewNum) {
        if (hintType==HintType.SMALL_CLUE || (!isType2 && hintType==HintType.HINT)) return null;
        Map<Cell, BitSet> result = new HashMap<Cell, BitSet>();
        result.put(rectangleCells.get(3), BitSetFactory.createOneElement(a));
		if (isType2) result.put(rectangleCells.get(2), BitSetFactory.createOneElement(b));
        return result;
    }
    
    @Override
    public Map<Cell, BitSet> getAddedPotentials(HintType hintType, int viewNum) {
        if (!isType2 || hintType!=HintType.HINT) return null;
        Map<Cell, BitSet> result = new HashMap<Cell, BitSet>();
        BitSet xSet = BitSetFactory.createOneElement(x);
        result.put(rectangleCells.get(3), xSet);
		result.put(rectangleCells.get(2), xSet);
        return result;
    }
    
    @Override
    public Map<ImmutableCell, BitSet> getRemovedPotentials(HintType hintType) {
        return (hintType==HintType.HINT) ? super.getRemovedPotentials(hintType) : null;
    }

    @Override
    public Collection<Link> getLinks(HintType hintType, int viewNum) {
        if (hintType!=HintType.HINT) return null;
        Collection<Link> result = new ArrayList<Link>();
        result.add(new Link(rectangleCells.get(0), 0, rectangleCells.get(1), 0));
        result.add(new Link(rectangleCells.get(1), 0, rectangleCells.get(3), 0));
        result.add(new Link(rectangleCells.get(3), 0, rectangleCells.get(2), 0));
        result.add(new Link(rectangleCells.get(2), 0, rectangleCells.get(0), 0));
        return result;
    }
    
    @Override
    public double getDifficulty() {
        return isType2 ? 4.5 : 4.7;
    }

    @Override
    public String getHintHtml(HintType hintType) {
        Cell cellA = rectangleCells.get(0);
        Cell cellB = rectangleCells.get(1);
        Cell cellC = rectangleCells.get(2);
        Cell cellD = rectangleCells.get(3);
        String html = HtmlLoader.loadHtml(getHintResource().hint(hintType));
        return HtmlLoader.format(html, cellA.toString(), cellB.toString(), cellC.toString(), cellD.toString(), a, b, x);
    }

	@Override
	public String getName() {
		return getHintResource().getName(isType2 ? 2 : 1);
	}

    @Override
    public Uri getLink() {
    	return getHintResource().getUrl();
	}

	@Override
	public String toString() {
        Cell[] cells = new Cell[4];
        rectangleCells.toArray(cells);
        return getName() + ": " + Cell.toFullString(cells) + " " + a + ", " + b; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}
	
	private HintResource getHintResource() {
        return isType2 ? HintResource.AVOIDABLE_RECTANGLE_2 : HintResource.AVOIDABLE_RECTANGLE_1;
	}

}